package logic;

import java.io.Serializable;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map.Entry;


public class GameMap implements Serializable {

	private static final long serialVersionUID = 1L;
	public HashMap<String, Country> countries;
	public HashMap<String, Integer> countriesIndex;
	private HashMap<String, Continent> continents;
	private boolean allCountriesSettled;
	

	public GameMap deepClone(){
		GameMap gameMap = new GameMap();
		gameMap.allCountriesSettled = this.allCountriesSettled;
		return gameMap;
	}

	public GameMap() {
		Continent NAmerica, SAmerica, Europe, Africa, Asia, Australia;
		Country Alaska, WCanada, CAmerica, EUStates, Greenland, NTerritory, CCanada, ECanada, WUStates;
		Country Argentina, Brazil, Peru, Venezuela;
		Country EAustralia, Indonesia, NGuinea, WAustralia;
		Country Iceland, GBritain, NEurope, Scandinavia, SEurope, Ukraine, WEurope;
		Country Afghanistan, China, India, Irkutsk, Japan, Kamchatka, MEast, Mongolia, Siam, Siberia, Ural, Yakutsk;
		Country CAfrica, EAfrica, Egypt, Madagascar, NAfrica, SAfrica;
		//Country Israel;
		
		this.continents= new HashMap<String, Continent>();
		this.countriesIndex=new HashMap<String, Integer>();
		this.countries= new HashMap<String, Country>();
		
		SAmerica = new Continent("South America", true);
		Europe = new Continent("Europe", true);
		NAmerica = new Continent("North America", true);
		Africa = new Continent("Africa", true);
		Asia = new Continent("Asia", false);
		Australia = new Continent("Australia", true);
		
		this.continents.put("Europe", Europe);
		this.continents.put("South America", SAmerica);
		this.continents.put("Asia", Asia);
		this.continents.put("North America", NAmerica);
		this.continents.put("Africa", Africa);
		this.continents.put("Australia", Australia);
		
		Alaska = new Country("Alaska");
		WCanada = new Country("Western Canada");
		CAmerica = new Country ("Central America");
		EUStates = new Country ("Eastern United States");
		Greenland = new Country("Greenland");
		NTerritory = new Country("Northwest Territory");
		CCanada = new Country ("Central Canada");
		ECanada = new Country("Eastern Canada");
		WUStates = new Country("Western United States");
		countries.put("Alaska", Alaska);
		countries.put("Western Canada", WCanada);
		countries.put("Central America", CAmerica);
		countries.put("Eastern United States", EUStates);
		countries.put("Greenland", Greenland);
		countries.put("Northwest Territory", NTerritory);
		countries.put("Central Canada", CCanada);
		countries.put("Eastern Canada", ECanada);
		countries.put("Western United States", WUStates);
		NAmerica.addCountry(Alaska);
		NAmerica.addCountry(WCanada);
		NAmerica.addCountry(CAmerica);
		NAmerica.addCountry(EUStates);
		NAmerica.addCountry(Greenland);
		NAmerica.addCountry(NTerritory);
		NAmerica.addCountry(CCanada);
		NAmerica.addCountry(ECanada);
		NAmerica.addCountry(WUStates);
		Alaska.addNeighbor(NTerritory);
		Alaska.addNeighbor(WCanada);
		WCanada.addNeighbor(NTerritory);
		WCanada.addNeighbor(CCanada);
		WCanada.addNeighbor(WUStates);
		CAmerica.addNeighbor(EUStates);
		CAmerica.addNeighbor(WUStates);
		EUStates.addNeighbor(CCanada);
		EUStates.addNeighbor(ECanada);
		EUStates.addNeighbor(WUStates);
		EUStates.addNeighbor(CAmerica);
		Greenland.addNeighbor(NTerritory);
		Greenland.addNeighbor(CCanada);
		Greenland.addNeighbor(ECanada);
		NTerritory.addNeighbor(Alaska);
		NTerritory.addNeighbor(WCanada);
		NTerritory.addNeighbor(CCanada);
		NTerritory.addNeighbor(Greenland);
		CCanada.addNeighbor(NTerritory);
		CCanada.addNeighbor(WCanada);
		CCanada.addNeighbor(WUStates);
		CCanada.addNeighbor(EUStates);
		CCanada.addNeighbor(ECanada);
		CCanada.addNeighbor(Greenland);
		ECanada.addNeighbor(EUStates);
		ECanada.addNeighbor(CCanada);
		ECanada.addNeighbor(Greenland);
		WUStates.addNeighbor(WCanada);
		WUStates.addNeighbor(CCanada);
		WUStates.addNeighbor(EUStates);
		WUStates.addNeighbor(CAmerica);
		
		Argentina = new Country("Argentina");
		Brazil = new Country("Brazil");
		Peru = new Country("Peru");
		Venezuela = new Country ("Venezuela");
		countries.put("Argentina", Argentina);
		countries.put("Brazil", Brazil);
		countries.put("Peru", Peru);
		countries.put("Venezuela", Venezuela);
		SAmerica.addCountry(Argentina);
		SAmerica.addCountry(Brazil);
		SAmerica.addCountry(Peru);
		SAmerica.addCountry(Venezuela);
		Argentina.addNeighbor(Brazil);
		Argentina.addNeighbor(Peru);
		Brazil.addNeighbor(Argentina);
		Brazil.addNeighbor(Peru);
		Brazil.addNeighbor(Venezuela);
		Peru.addNeighbor(Argentina);
		Peru.addNeighbor(Venezuela);
		Peru.addNeighbor(Brazil);
		Venezuela.addNeighbor(Brazil);
		Venezuela.addNeighbor(CAmerica);
		Venezuela.addNeighbor(Peru);
		CAmerica.addNeighbor(Venezuela);
		EAustralia = new Country("Eastern Australia");
		Indonesia = new Country("Indonesia");
		NGuinea = new Country ("New Guinea");
		WAustralia = new Country ("Western Australia");
		countries.put("Eastern Australia", EAustralia);
		countries.put("Indonesia", Indonesia);
		countries.put("New Guinea", NGuinea);
		countries.put("Western Australia", WAustralia);
		Australia.addCountry(EAustralia);
		Australia.addCountry(Indonesia);
		Australia.addCountry(NGuinea);
		Australia.addCountry(WAustralia);
		EAustralia.addNeighbor(WAustralia);
		EAustralia.addNeighbor(NGuinea);
		Indonesia.addNeighbor(NGuinea);
		Indonesia.addNeighbor(WAustralia);
		NGuinea.addNeighbor(EAustralia);
		NGuinea.addNeighbor(Indonesia);
		NGuinea.addNeighbor(WAustralia);
		WAustralia.addNeighbor(EAustralia);
		WAustralia.addNeighbor(Indonesia);
		WAustralia.addNeighbor(NGuinea);

		Iceland = new Country("Iceland");
		GBritain = new Country("Great Britain");
		NEurope = new Country ("Northern Europe");
		Scandinavia = new Country ("Scandinavia");
		SEurope = new Country("Southern Europe");
		Ukraine = new Country("Ukraine");
		WEurope = new Country("Western Europe");
		countries.put("Iceland", Iceland);
		countries.put("Great Britain", GBritain);
		countries.put("Northern Europe", NEurope);
		countries.put("Scandinavia", Scandinavia);
		countries.put("Southern Europe", SEurope);
		countries.put("Ukraine", Ukraine);
		countries.put("Western Europe", WEurope);
		Europe.addCountry(Iceland);
		Europe.addCountry(GBritain);
		Europe.addCountry(NEurope);
		Europe.addCountry(Scandinavia);
		Europe.addCountry(SEurope);
		Europe.addCountry(Ukraine);
		Europe.addCountry(WEurope);
		Iceland.addNeighbor(GBritain);
		Iceland.addNeighbor(Scandinavia);
		Iceland.addNeighbor(Greenland);
		Greenland.addNeighbor(Iceland);
		GBritain.addNeighbor(Iceland);
		GBritain.addNeighbor(Scandinavia);
		GBritain.addNeighbor(NEurope);
		GBritain.addNeighbor(WEurope);
		NEurope.addNeighbor(GBritain);
		NEurope.addNeighbor(Scandinavia);
		NEurope.addNeighbor(Ukraine);
		NEurope.addNeighbor(SEurope);
		NEurope.addNeighbor(WEurope);
		Scandinavia.addNeighbor(Iceland);
		Scandinavia.addNeighbor(GBritain);
		Scandinavia.addNeighbor(NEurope);
		Scandinavia.addNeighbor(Ukraine);
		SEurope.addNeighbor(WEurope);
		SEurope.addNeighbor(NEurope);
		SEurope.addNeighbor(Ukraine);
		Ukraine.addNeighbor(SEurope);
		Ukraine.addNeighbor(NEurope);
		Ukraine.addNeighbor(Scandinavia);
		WEurope.addNeighbor(GBritain);
		WEurope.addNeighbor(NEurope);
		WEurope.addNeighbor(SEurope);
		Afghanistan = new Country("Afghanistan");
		China = new Country("China");
		India = new Country("India");
		Irkutsk = new Country("Irkutsk");
		Japan = new Country("Japan");
		Kamchatka = new Country("Kamchatka");
		MEast = new Country("Middle East");
		Mongolia = new Country("Mongolia");
		Siam  = new Country("Siam");
		Siberia = new Country("Siberia");
		Ural = new Country("Ural");
		Yakutsk = new Country("Yakutsk");
		countries.put("Afghanistan", Afghanistan);
		countries.put("China", China);
		countries.put("India", India);
		countries.put("Irkutsk", Irkutsk);
		countries.put("Japan", Japan);
		countries.put("Kamchatka", Kamchatka);
		countries.put("Middle East",MEast);
		countries.put("Mongolia", Mongolia);
		countries.put("Siam", Siam);
		countries.put("Siberia", Siberia);
		countries.put("Ural",Ural);
		countries.put("Yakutsk",Yakutsk);
		Asia.addCountry(Afghanistan);
		Asia.addCountry(China);
		Asia.addCountry(India);
		Asia.addCountry(Irkutsk);
		Asia.addCountry(Japan);
		Asia.addCountry(Kamchatka);
		Asia.addCountry(MEast);
		Asia.addCountry(Mongolia);
		Asia.addCountry(Siam);
		Asia.addCountry(Siberia);
		Asia.addCountry(Ural);
		Asia.addCountry(Yakutsk);
		Afghanistan.addNeighbor(Ural);
		Afghanistan.addNeighbor(China);
		Afghanistan.addNeighbor(India);
		Afghanistan.addNeighbor(MEast);
		China.addNeighbor(Afghanistan);
		China.addNeighbor(Ural);
		China.addNeighbor(Siberia);
		China.addNeighbor(Mongolia);
		China.addNeighbor(Siam);
		China.addNeighbor(India);
		India.addNeighbor(MEast);
		India.addNeighbor(Afghanistan);
		India.addNeighbor(China);
		India.addNeighbor(Siam);
		Irkutsk.addNeighbor(Siberia);
		Irkutsk.addNeighbor(Yakutsk);
		Irkutsk.addNeighbor(Kamchatka);
		Irkutsk.addNeighbor(Mongolia);
		Japan.addNeighbor(Kamchatka);
		Japan.addNeighbor(Mongolia);
		Kamchatka.addNeighbor(Yakutsk);
		Kamchatka.addNeighbor(Irkutsk);
		Kamchatka.addNeighbor(Mongolia);
		Kamchatka.addNeighbor(Japan);
		Kamchatka.addNeighbor(Alaska);
		Alaska.addNeighbor(Kamchatka);
		MEast.addNeighbor(Ukraine);
		MEast.addNeighbor(Afghanistan);
		MEast.addNeighbor(India);
		MEast.addNeighbor(SEurope);
		SEurope.addNeighbor(MEast);
		India.addNeighbor(MEast);
		Mongolia.addNeighbor(Siberia);
		Mongolia.addNeighbor(Irkutsk);
		Mongolia.addNeighbor(Kamchatka);
		Mongolia.addNeighbor(Japan);
		Mongolia.addNeighbor(China);
		Siam.addNeighbor(India);
		Siam.addNeighbor(China);
		Siam.addNeighbor(Indonesia);
		Indonesia.addNeighbor(Siam);
		Siberia.addNeighbor(Ural);
		Siberia.addNeighbor(China);
		Siberia.addNeighbor(Mongolia);
		Siberia.addNeighbor(Irkutsk);
		Siberia.addNeighbor(Yakutsk);
		Ural.addNeighbor(Siberia);
		Ural.addNeighbor(China);
		Ural.addNeighbor(Afghanistan);
		Ural.addNeighbor(Ukraine);
		Ukraine.addNeighbor(Ural);
		Afghanistan.addNeighbor(Ukraine);
		Ukraine.addNeighbor(Afghanistan);
		Yakutsk.addNeighbor(Siberia);
		Yakutsk.addNeighbor(Irkutsk);
		Yakutsk.addNeighbor(Kamchatka);
		
		CAfrica = new Country("Central Africa");
		EAfrica = new Country("East Africa");
		Egypt = new Country("Egypt");
		Madagascar = new Country("Madagascar");
		NAfrica = new Country("North Africa");
		SAfrica = new Country("South Africa");
		countries.put("Central Africa", CAfrica);
		countries.put("East Africa", EAfrica);
		countries.put("Egypt", Egypt);
		countries.put("Madagascar", Madagascar);
		countries.put("North Africa",NAfrica);
		countries.put("South Africa", SAfrica);
		Africa.addCountry(CAfrica);
		Africa.addCountry(EAfrica);
		Africa.addCountry(Egypt);
		Africa.addCountry(Madagascar);
		Africa.addCountry(NAfrica);
		Africa.addCountry(SAfrica);
		CAfrica.addNeighbor(NAfrica);
		CAfrica.addNeighbor(EAfrica);
		CAfrica.addNeighbor(SAfrica);
		EAfrica.addNeighbor(Madagascar);
		EAfrica.addNeighbor(SAfrica);
		EAfrica.addNeighbor(CAfrica);
		EAfrica.addNeighbor(NAfrica);
		EAfrica.addNeighbor(Egypt);
		EAfrica.addNeighbor(MEast);
		MEast.addNeighbor(EAfrica);
		Egypt.addNeighbor(NAfrica);
		Egypt.addNeighbor(EAfrica);
		Egypt.addNeighbor(MEast);
		MEast.addNeighbor(Egypt);
		Egypt.addNeighbor(SEurope);
		SEurope.addNeighbor(Egypt);
		Madagascar.addNeighbor(EAfrica);
		Madagascar.addNeighbor(SAfrica);
		NAfrica.addNeighbor(Egypt);
		NAfrica.addNeighbor(EAfrica);
		NAfrica.addNeighbor(CAfrica);
		NAfrica.addNeighbor(Brazil);
		Brazil.addNeighbor(NAfrica);
		SAfrica.addNeighbor(Madagascar);
		SAfrica.addNeighbor(EAfrica);
		SAfrica.addNeighbor(CAfrica);	
		WEurope.addNeighbor(NAfrica);
		NAfrica.addNeighbor(WEurope);
		Ukraine.addNeighbor(MEast);
		//Israel = new Country("Israel");
		//countries.put("Israel", Israel);
		//Asia.addCountry(Israel);
		//Israel.addNeighbor(MEast);
		//MEast.addNeighbor(Israel);
		//Israel.addNeighbor(Egypt);
		//Egypt.addNeighbor(Israel);
		allCountriesSettled=false;
		
		int i=0;
		for (Country country : countries.values()) {
			countriesIndex.put(country.getName(), i++);
		}
		
	}

	public String toString(){
		String str="";
		for(Continent continent : this.continents.values()){
			str += continent.getName() + ":\n";
			for(Country country : continent.getTerritoriesContained()){
				str += "\tCountry: " + country + "\n" + "\tOccupied by: ";
				str += (country.getOwner() == null)? "Not occupied" : country.getOwner().getPlayerName();
				str += "\n\tNumber of soldiers: " + country.getSoldiers(); 
				str += "\n\tNeighbours: ";
				HashMap<String, Country> neighbours = country.getNeighbors();
				for(Entry<String,Country> entryNeighbour : neighbours.entrySet()){
					str += entryNeighbour.getValue() + ", ";
				}
				str += "\n\tCan attack: ";
				for(Entry<String,Country> entryNeighbour : neighbours.entrySet()){
					if(entryNeighbour.getValue().getOwner() != country.getOwner()
							&& (entryNeighbour.getValue().getSoldiers() > 0)){
						str += entryNeighbour.getValue() + " ";
					}
				}
				str += "\n\n";
			}
		}
		return str;
	}
	
	public HashMap<String, Country> getCountries() {
		return countries;
	}

	public static void relateNeighbours(Country first, Country second)
	{
		first.addNeighbor(second);
		second.addNeighbor(first);
	}

	public boolean allCountriesSettled(){
		if (!allCountriesSettled)
			for(Entry<String,Country> country : countries.entrySet())
				if (!country.getValue().hasOwner())
					return false;
		allCountriesSettled=true;
		return allCountriesSettled;
	}
	
	public Continent getContinentFromName(String continentName){
		Continent continent;
		continent = continents.get(continentName);
		return continent;
	}
	
	/**
	 * returns an array representation of the unsettles countries
	 */
	public Country[] getUnsettledCountries(){
		List<Country> unsettled = new LinkedList<Country>();
		for(Country country : this.countries.values()){
			if(country.getOwner() == null){
				unsettled.add(country);
			}
		}
		return unsettled.toArray(new Country[unsettled.size()]);
	}
	
	/**
	 * return all the players countries if mine == true or
	 * all the other if mine == false
	 */
	public Country[] getPlyersCountries(Player player, boolean mine){
		List<Country> counrtries = new LinkedList<Country>();
		for(Country country : this.countries.values()){
			if(country.getOwner() == null){
				continue;
			}
			if(country.getOwner().equals(player) && mine){
				counrtries.add(country);
			} else if(!country.getOwner().equals(player) && !mine){
				counrtries.add(country);
			}
		}
		return counrtries.toArray(new Country[counrtries.size()]);
	}
	
	/**
	 * return all the players countries if mine == true or
	 * all the other if mine == false which are neighbors with neighbor
	 */
	public Country[] getPlyersCountries(Player player, boolean mine, Country neighbor){
		List<Country> counrtries = new LinkedList<Country>();
		for(Country country : this.countries.values()){
			if(country.getOwner() == null){
				continue;
			}
			if(country.getOwner().equals(player) && mine && Country.isNeighbors(country, neighbor)){
				counrtries.add(country);
			} else if(!country.getOwner().equals(player) && !mine && Country.isNeighbors(country, neighbor)){
				counrtries.add(country);
			}
		}
		return counrtries.toArray(new Country[counrtries.size()]);
	}

	public HashMap<String, Continent> getContinents() {
		return continents;
	}
	
	public int getCountryIndex(Country country){
		return countriesIndex.get(country.getName());
	}
	
	public Country getCountry(String name){
		return this.countries.get(name);
	}
}
